/**
* 
* ver 7.0 注意建摸工具是右手坐标系，我的引擎是左手坐标系，
* 所以我在读取模型的时候进行了坐标转换，把模型里的x=-x了，
*	这样带来的结果就是进行背面剔除的时候cullType相关的东西是做成左手坐标要
*
*ver 8.0 注意建模和最终读取的时候的坐标系即可
*
*注意3dmax导出obj的时候要选上“导出相对位置”。这个是为了导出多个模型用的
*相对位置是vertextCount+相对位置索引。实际上是顶点缓冲的最后一个为-1,上一个为-2
*
*这个可以导出多个模型，3dmax中模型为z上，y里，x右，到我的世界中,y上，z里，x右
*如果是导出多个模型，则模型会有名字的
*
*注意这个和objParser功能重复，可以考虑去掉
*这个只是负责加载，不负责解析
*/
package kgame5.k3d.util3d.loader3d {
import kgame5.k3d.core.math.NumberUV;
import kgame5.k3d.core.math.Vector3D;
import kgame5.k3d.core.math.Vertex3D;
import kgame5.k3d.core.obj3d.info.geometry.Face3D;
import kgame5.k3d.core.obj3d.info.geometry.GeometryInfo;
import kgame5.k3d.core.obj3d.node3d.impl.mesh.Mesh3D;
import kgame5.kutil.*;

import flash.events.*;
import flash.net.*;
import flash.utils.Dictionary;

public class Loader3DObjX extends EventDispatcher{
	
	public static const 
		EVENTTYPE_ALL_MESH3D_LOADOK:String="EVENTTYPE_ALL_MESH3D_LOADOK";
		
	//dict[name]=mesh3D
	public var dict_mesh:Dictionary=new Dictionary();//导出的是多个模型
	
	public var _firstMesh3D:Mesh3D=null;
	
	public function Loader3DObjX(){
		
	}
	
	//*********************加载3dmax格式的数据***********************
	//开始加载
	public  function Load(sFileUrl:String):void{
		var l:URLLoader=new URLLoader();
		l.addEventListener(Event.COMPLETE,onComplete);
				
		try{
			l.load(new URLRequest(sFileUrl));
		}catch(er:Error){
			T.p("不能加载，发生错误");
		}
	}

    //加载成功后调用这个
	 private function onComplete(e:Event):void {
	 	//T.p(this,"onComplete");
		var l:URLLoader=URLLoader(e.target); 
		
		//1,分割text为一个字符数组
		var sSrc:String=l.data as String;

		var aText:Array=sSrc.split(/\ng\n/);//分割成一个组一个组的
	
		var len:int=aText.length-1;//注意aText的最后一个是个长度为0，是个NaN的字符串，大概是文本结束标志吧
		
		//导出的是多个模型
		for(var i:int=0;i<len;i++){
	        var mesh:Mesh3D=readMesh3D(aText[i]);
	        dict_mesh[mesh.name]=mesh;
	        
	        if(_firstMesh3D==null){//设置好第一个模型，这个就是为了照顾老程序而用的
	        	_firstMesh3D=mesh;	
	        }
	        	
	        //T.p("读取一个Mesh3D成功", mesh.name);
		}

      	this.dispatchEvent(new KEvent(EVENTTYPE_ALL_MESH3D_LOADOK));
     }
   
	/*这个就是一个数据组
	# object Object01 to come ...
	#
	v  4.71292305 7.57816410 -0.01040745
	# 12 vertices
	
	vt  0.31992051 0.83834887 1.50000000
	# 30 texture vertices
	
	g Object01
	f 92/57 93/58 86/61
	# 20 faces
	
	*/
	//从一个数据组里读取出数据
	private function readMesh3D(sData:String):Mesh3D{
		
		//1,提取名字，简单情况下用正则表达式很好
		var rg:RegExp=/# object ([\w\d]+) to come/;
		var name:String=rg.exec(sData)[1];
		
		var aText:Array=sData.split("\n");

		//---提取自己感兴趣的3个数组
		var gi:GeometryInfo=new GeometryInfo();
		
		//var aVertex:Vector.<Vertex3D>;
		gi.aVertex=new Vector.<Vertex3D>();
		
		gi.aFace=new Vector.<Face3D>();
		
		gi.aUV = new Vector.<NumberUV>();
		
		var aVB_p:Vector.<Vector3D> =new Vector.<Vector3D>();
		var aVB_t:Vector.<Number> =new Vector.<Number>();

		
		var a2IB_p:Array=new Array();
		var a2IB_t:Array=new Array();
		
		var i:int;
		var len:int;
		
		//注意一个obj里如果包含多个模型，则需要的是相对顶点索引，否则v,vt索引就是对于整个模型来说的索引了
		var textureVerticesCount:int=0;
		var verticesCount:int=0;
		
		//T.p("开始就解吸");
		len=aText.length;
		for(i=0;i<len;i++){
			//1,每一行的数据解析成数组
			var aItem:Array=aText[i].split(" ");//每个条目
			//注意这个结果是长度是5,因为v后是两个空格
			//v  -6.05815268 14.48638535 -26.09479904
			
			//2,根据行头的标号来处理
			var head:String=aItem[0];
			
			//注意这么提取顶点数也是很有讲究的,因为"texture vertices"里也有"vertices"
			//不精心处理会导致数值覆盖
			if(aText[i].indexOf("texture vertices")!=-1){
				textureVerticesCount=parseInt(aItem[1]);
				//T.p("textureVerticesCount",textureVerticesCount);
			}else {
				if(aText[i].indexOf("vertices") != -1) {
					verticesCount = parseInt(aItem[1]);
					//T.p("verticesCount", verticesCount);
				}
			}
			
			//ttt(i+"行的aItem为_"+head,aItem);
			switch(head){
				case "v":
					//T.p("这个是v!!");
					//T.p(parseInt(aItem[1])+" "+parseInt(aItem[2])+" "+parseInt(aItem[3])+" ");
					//aVB_p.push(parseFloat(aItem[2]));//转换到左手坐标,挺乱的，目的是让模型0角度为z轴
					//aVB_p.push(parseFloat(aItem[3]));
					//aVB_p.push(-parseFloat(aItem[4]));
					
					var vv:Vector3D=new Vector3D();
					vv.x=parseFloat(aItem[2]);
					vv.y=parseFloat(aItem[3]);
					vv.z=-parseFloat(aItem[4]);
					
					aVB_p.push(vv);
					
					//-
					var vx:Vertex3D=new Vertex3D(0,0,0);
					vx.x=vv.x;
					vx.y=vv.y;
					vx.z=vv.z;
					gi.aVertex.push(vx);
					
//					aVB_p.push(-parseFloat(aItem[2]));//转换到左手坐标,挺乱的，目的是让模型0角度为z轴
//					aVB_p.push(parseFloat(aItem[3]));
//					aVB_p.push(parseFloat(aItem[4]));
				break;
				case "vt":
					//T.p("这个是vt!!");
					var _u:Number=parseFloat(aItem[2]);
					var _v:Number=1-parseFloat(aItem[3]);
					aVB_t.push(_u);
					aVB_t.push(_v);//严重注意，这里需要1-,不这么做就会贴图不正确
					
					gi.aUV.push(new NumberUV(_u,_v));
					
				break;
				case "f"://每个三角面的信息,f 始终是3个的。"f -19/-46 -17/-45 -18/-44"
					//T.p("这个是f!!");
					//part 1:顶点索引.-1是因为他是从1开始的
					var a:int=verticesCount+parseInt((aItem[1].split("/"))[0]);//-verticesCount;
					var b:int=verticesCount+parseInt((aItem[2].split("/"))[0]);//-verticesCount;
					var c:int=verticesCount+parseInt((aItem[3].split("/"))[0]);//-verticesCount;
					
					a2IB_p.push([a,b,c]);//一个三角条带
					
					//part 2:真正的各个面的纹理,这些是索引
					var at:int=textureVerticesCount+parseInt((aItem[1].split("/"))[1]);//-textureVerticesCount;
					var bt:int=textureVerticesCount+parseInt((aItem[2].split("/"))[1]);//-textureVerticesCount;
					var ct:int=textureVerticesCount+parseInt((aItem[3].split("/"))[1]);//-textureVerticesCount;
					
					a2IB_t.push([at,bt,ct]);//一个三角条带
					
					//T.p("!22",a,b,c);
					//T.p("!33",at,bt,ct);
					
					gi.aFace.push(new Face3D(gi,a,b,c,at,bt,ct));
					
				break;
			}
		}
		//
		//T.p("--------------解吸完毕----------------");
		//ttt("顶点",aVB_p);
		//ttt("文理",aVB_t);
		//ttt("三角条顶点索引",a2IB_p);
		//ttt("三角条纹理索引",a2IB_t);
		
		//---------生成data3D
		
		//gi.aVertex=aVertex;
		// 建造各个face
//		for(var i:int=0;i<a2IB_p.length;i++){
//			var a:int=a2IB_p[i][0];
//			var b:int=a2IB_p[i][1];
//			var c:int=a2IB_p[i][2];
//			
//			var at:int=a2IB_t[i][0];
//			var bt:int=a2IB_t[i][1];
//			var ct:int=a2IB_t[i][2];
//			
//			gi.aFace.push(new Face3D(aVertex[a],aVertex[b],aVertex[c],aNumberUV[at],aNumberUV[bt],aNumberUV[ct]));
//		}

		//var bmd:BitmapData=new BitmapData(2,2,false,0x00ff00);////2,测试用的贴图

		//-----生成mesh
		var mesh:Mesh3D=new Mesh3D();
		mesh.name=name;
		
		mesh.setGeometryInfo(gi);
		//mesh.mi.bitmap=bmd;
		

		return mesh;
	}
}//end of class
}